﻿using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using ToyStore.Domain.Common;
using ToyStore.Domain.Contracts.Tasks;
using ToyStore.Domain.System;
using ToyStore.Infrastructure;

namespace ToyStore.Tasks
{
	public class SettingTasks : ISettingTasks
	{
		private readonly IExRepository<Setting> _settingsRepository;

		public SettingTasks(IExRepository<Setting> settingsRepository)
		{
			_settingsRepository = settingsRepository;

			LoadSettings();
		}

		/// <summary>
		/// Adres serwera pocztowego
		/// </summary>
		[DatabaseId(1)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public string SmtpServer { get; private set; }

		/// <summary>
		/// Port serwera pocztowego
		/// </summary>
		[DatabaseId(2)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public int SmtpPort { get; private set; }

		/// <summary>
		/// Login do serwera pocztowego
		/// </summary>
		[DatabaseId(3)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public string SmtpLogin { get; private set; }

		/// <summary>
		/// Hasło do serwera pocztowego
		/// </summary>
		[DatabaseId(4)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public string SmtpPassword { get; private set; }

		/// <summary>
		/// Nazwa nadawcy 
		/// </summary>
		[DatabaseId(5)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public string SmtpSenderName { get; private set; }

		/// <summary>
		/// Email Nadawcy
		/// </summary>
		[DatabaseId(6)]
		[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
		public string SmtpSenderAddress { get; private set; }

		/// <summary>
		/// Pobranie ustawień z bazy danych i wpisanie do publicznych statycznych propertisów z odpowiednimi atrybutami
		/// </summary>
		public void LoadSettings()
		{
			foreach (PropertyInfo value in typeof(SettingTasks).GetProperties())
			{
				var attribute = value.GetCustomAttributes(typeof(DatabaseIdAttribute), true).FirstOrDefault() as DatabaseIdAttribute;

				if (attribute != null)
				{
					Setting setting = _settingsRepository.Get(attribute.Id);

					if (setting != null)
					{
						value.SetValue(this, GetSettingsValue(value, setting.Value), null);
					}
					else
					{
						//Logger.Instance.ErrorFormat("Brak wartości dla ustawienia: {0}.", value.Name);
					}
				}
			}
		}

		/// <summary>
		/// Konwersja pobranego z bazy danych ustawienia zapisanego jako string,
		/// do typu odpowiedniego dla danego propertisa
		/// </summary>
		/// <param name="propertyInfo"></param>
		/// <param name="fieldStrValue"></param>
		/// <returns></returns>
		private static object GetSettingsValue(PropertyInfo propertyInfo, string fieldStrValue)
		{
			object fieldValue;

			if (propertyInfo.PropertyType == typeof(bool))
			{
				fieldValue = fieldStrValue == "1";
			}
			else if (propertyInfo.PropertyType == typeof(int))
			{
				int numericValue;
				if (int.TryParse(fieldStrValue, out numericValue))
					fieldValue = numericValue;
				else
					fieldValue = propertyInfo.GetValue(propertyInfo, null);
			}
			else if (propertyInfo.PropertyType == typeof(string))
			{
				if (fieldStrValue == null)
					fieldStrValue = string.Empty;
				fieldValue = fieldStrValue;
			}
			else
			{
				throw new NotImplementedException("Zaimplementuj obsługę typu");
			}

			return fieldValue;
		}
	}
}
